// Copyright by Scot Drysdale

package cn.edu.nju.software.grapheditor;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

import cn.edu.nju.software.grapheditor.cmd.*;

public class Editor extends JApplet {
	private static final long serialVersionUID = 1L;

	private final int APPLET_WIDTH = 700, APPLET_HEIGHT = 500;
	private final Color initialColor = Color.red; // default color starts as red

	private JLabel status;
	private CanvasPanel cp;
	private Command cmd; // the command being executed
	private Drawing dwg; // the drawing: shapes in order
	private ColorIndicator colorBox; // a GUI component to show the current
										// default color

	public void init() {
		cmd = new Command(); // all methods in Command are empty
		dwg = new Drawing(initialColor); // make an empty drawing

		// The drawing will appear in a white CanvasPanel.
		CanvasPanel canvasPanel = new CanvasPanel();
		this.cp=canvasPanel;
		canvasPanel.setBackground(Color.white);

		// Make JButton objects for all the command buttons.
		JButton rectButton = new JButton("Rectangle");
		JButton ovalButton = new JButton("Oval");
		JButton lineButton = new JButton("Line");
		JButton moveButton = new JButton("Move");
		JButton deleteButton = new JButton("Delete");
		JButton frontButton = new JButton("Front");
		JButton backButton = new JButton("Back");
		JButton exchangeButton = new JButton("Exchange");
		JButton copyButton=new JButton("Copy");
		JButton redButton = new JButton("Red");
		JButton greenButton = new JButton("Green");
		JButton blueButton = new JButton("Blue");

		// Add listeners for all the command buttons.
		rectButton.addActionListener(new RectButtonListener());
		ovalButton.addActionListener(new OvalButtonListener());
		lineButton.addActionListener(new LineButtonListener());
		moveButton.addActionListener(new MoveButtonListener());
		deleteButton.addActionListener(new DeleteButtonListener());
		frontButton.addActionListener(new FrontButtonListener());
		backButton.addActionListener(new BackButtonListener());
		exchangeButton.addActionListener(new ExchangeButtonListener());
		copyButton.addActionListener(new CopyButtonListener());
		redButton.addActionListener(new RedButtonListener());
		greenButton.addActionListener(new GreenButtonListener());
		blueButton.addActionListener(new BlueButtonListener());

		// The command buttons will be arranged in 3 rows.
		// Each row will appear in its own JPanel, and the 3 JPanels will
		// be stacked vertically.
		JPanel shapePanel = new JPanel(); // holds buttons for adding shapes
		JLabel shapeLabel = new JLabel("Add shape:");
		shapePanel.setLayout(new FlowLayout());
		shapePanel.add(shapeLabel);
		rectButton.setBackground(Color.yellow);
		ovalButton.setBackground(Color.yellow);
		lineButton.setBackground(Color.yellow);
		shapePanel.add(rectButton);
		shapePanel.add(ovalButton);
		shapePanel.add(lineButton);

		JPanel editPanel = new JPanel(); // holds buttons for editing operations
		JLabel editLabel = new JLabel("Edit:");
		editPanel.setLayout(new FlowLayout());
		editPanel.add(editLabel);
		moveButton.setBackground(Color.yellow);
		deleteButton.setBackground(Color.yellow);
		frontButton.setBackground(Color.yellow);
		backButton.setBackground(Color.yellow);
		exchangeButton.setBackground(Color.yellow);
		copyButton.setBackground(Color.green);
		editPanel.add(moveButton);
		editPanel.add(deleteButton);
		editPanel.add(frontButton);
		editPanel.add(backButton);
		editPanel.add(exchangeButton);
		editPanel.add(copyButton);

		// The color panel is slightly different from the other two. In addition
		// to a label and buttons for the color commands, this panel holds a
		// ColorIndicator that gives the current default color.
		JPanel colorPanel = new JPanel();
		JLabel colorLabel = new JLabel("Colors:");
		colorPanel.setLayout(new FlowLayout());
		colorPanel.add(colorLabel);
		colorBox = new ColorIndicator();
		colorBox.show(initialColor);
		redButton.setBackground(Color.yellow);
		greenButton.setBackground(Color.yellow);
		blueButton.setBackground(Color.yellow);
		colorPanel.add(colorBox);
		colorPanel.add(redButton);
		colorPanel.add(greenButton);
		colorPanel.add(blueButton);

		// Use a grid layout to stack the button panels vertically.
		// Also, give them a cyan background.
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new GridLayout(3, 1));
		shapePanel.setBackground(Color.cyan);
		editPanel.setBackground(Color.cyan);
		colorPanel.setBackground(Color.cyan);
		JLabel statusLabel=new JLabel("Current button:");
		JLabel statusfield=new JLabel("None");
		statusfield.setText("None");
		this.status=statusfield;
		buttonPanel.add(shapePanel);
		buttonPanel.add(editPanel);
		buttonPanel.add(colorPanel);
		colorPanel.add(statusLabel);
		colorPanel.add(statusfield);

		// Now we have two panels: buttonPanel and canvasPanel. We want
		// buttonPanel to appear above canvasPanel, and canvasPanel should grow
		// with the applet.
		Container cp = getContentPane();
		cp.setLayout(new BorderLayout());
		cp.add(buttonPanel, BorderLayout.NORTH);
		cp.add(canvasPanel, BorderLayout.CENTER);

		setSize(APPLET_WIDTH, APPLET_HEIGHT);
	}

	public void paint(Graphics page) {
		super.paint(page); // make all the GUI components paint themselves
	}

	// What to do when rectButton is pressed.
	private class RectButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Rectangle");
			cmd=new RectangleCmd(cp.getGraphics());
			repaint();
		}
	}

	// What to do when ovalButton is pressed.
	private class OvalButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Oval");
			cmd=new OvalCmd(cp.getGraphics());
			repaint();
		}
	}

	// What to do when lineButton is pressed.
	private class LineButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Line");
			cmd=new LineCmd(cp.getGraphics());
			repaint();
		}
	}

	// What to do when moveButton is pressed.
	private class MoveButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Move");
			cmd=new MoveCmd();
			repaint();
		}
	}

	// What to do when deleteButton is pressed.
	private class DeleteButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Delete");
			cmd=new DeleteCmd(cp.getGraphics());
			repaint();
		}
	}

	// What to do when frontButton is pressed.
	private class FrontButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Front");
			cmd=new FrontCmd();
			repaint();
		}
	}

	// What to do when backButton is pressed.
	private class BackButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Back");
			cmd=new BackCmd();
			repaint();
		}
	}

	// What to do when exchangeButton is pressed.
	private class ExchangeButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Exchange");
			cmd=new ExchangeCmd();
			dwg.draw(cp.getGraphics());
			repaint();
		}
	}
    
	// What to do when copy is pressed.
	private class CopyButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent arg0) {
			status.setText("Copy");
			cmd=new CopyCmd(cp.getGraphics());
			repaint();
		}
		
	}
	// What to do when redButton is pressed.
	private class RedButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Red");
			colorBox.show(Color.red); // show that the new default color is red
			dwg.setColor(Color.red);
			cmd=new ColorCmd(Color.red,cp.getGraphics());
			repaint();
		}
	}

	// What to do when greenButton is pressed.
	private class GreenButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Green");
			colorBox.show(Color.green); // show that the new default color is
										// green
			dwg.setColor(Color.green);
			cmd=new ColorCmd(Color.green,cp.getGraphics());
			repaint();
		}
	}

	// What to do when blueButton is pressed.
	private class BlueButtonListener implements ActionListener {
		public void actionPerformed(ActionEvent event) {
			status.setText("Blue");
			colorBox.show(Color.blue); // show that the new default color is
										// blue
			dwg.setColor(Color.blue);
			cmd=new ColorCmd(Color.blue,cp.getGraphics());
			repaint();
		}
	}

	// A ColorIndicator shows what the current color is.
	private class ColorIndicator extends JPanel {
		private static final long serialVersionUID = 0;

		private final int COLORBOX_WIDTH = 20, COLORBOX_HEIGHT = 20;

		// Constructor sets the size and border.
		public ColorIndicator() {
			setBorder(BorderFactory.createEtchedBorder());
			setPreferredSize(new Dimension(COLORBOX_WIDTH, COLORBOX_HEIGHT));
		}

		// Show a new color.
		public void show(Color color) {
			setBackground(color);
		}
	}

	// CanvasPanel is the class upon which we actually draw.
	// It listens for mouse events and calls the appropriate method of the
	// current command.
	private class CanvasPanel extends JPanel implements MouseListener,
			MouseMotionListener {
		private static final long serialVersionUID = 0;

		// Constructor just needs to set up the CanvasPanel as a listener.
		public CanvasPanel() {
			addMouseListener(this);
			addMouseMotionListener(this);
		}

		public void paint(Graphics page) {
			super.paint(page); // execute the paint method of JPanel
			dwg.draw(page); // have the drawing draw itself
		}

		// When the mouse is clicked, call the executeClick method of the
		// current command.
		public void mouseClicked(MouseEvent event) {
			cmd.executeClick(event.getPoint(), dwg);
			repaint();
		}

		// When the mouse is pressed, call the executePress method of the
		// current command.
		public void mousePressed(MouseEvent event) {
			cmd.executePress(event.getPoint(), dwg);
			repaint();
		}

		// When the mouse is dragged, call the executeDrag method of the current
		// command.
		public void mouseDragged(MouseEvent event) {
			cmd.executeDrag(event.getPoint(), dwg);
			repaint();
		}

		// We don't care about the other mouse events.
		public void mouseReleased(MouseEvent event) {
		}

		public void mouseEntered(MouseEvent event) {
		}

		public void mouseExited(MouseEvent event) {
		}

		public void mouseMoved(MouseEvent event) {
		}
	}
}
